<template>
  <div class="river-modal">
    <el-dialog width="70%" v-model="dialogVisible" :before-close="handleClose">
      <template #header="{ close, titleId, titleClass }">
        <div class="my-header">
          <div>{{ state.title }}</div>
        </div>
      </template>
      <div class="river-box">
        <el-form
          ref="riverFormRef"
          :model="state.riverForm"
          :rules="rules"
          label-width="auto"
          class="demo-ruleForm"
          status-icon
        >
          <el-form-item label="河系名称" prop="rsysName">
            <el-input class="formwidth" placeholder="请输入" v-model="state.riverForm.rsysName" />
          </el-form-item>
          <el-form-item label="河系说明" prop="rsysDesc">
            <el-input
              class="formwidth"
              type="textarea"
              placeholder="请输入"
              v-model="state.riverForm.rsysDesc"
            />
          </el-form-item>
          <el-form-item label="输入区域" prop="schemeType">
            <el-table
              ref="multipleTableRef"
              :data="state.tableData"
              style="width: 100%"
              class="areaTable"
              @select="handleSelectionChange"
            >
              <el-table-column property="calczName" label="区域名称" show-overflow-tooltip />
              <el-table-column property="creatorName" label="创建人" />
              <el-table-column property="createTime" label="创建时间" show-overflow-tooltip />
              <el-table-column type="selection" width="55" :selectable="handleSelectable" />
            </el-table>
          </el-form-item>
        </el-form>
        <div class="box-right">
          <div id="container"></div>
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="handleSave">保存</el-button>
          <el-button @click="handleClose()">取消</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, defineExpose } from 'vue'
import { getAreaList, addRiver, getZoneList, updateRiver } from '@/services/modules/compute-methods'
import { getMapAssetURL } from '@/utils/loadAssets'
import { ElMessage, ElMessageBox } from 'element-plus'
import G6 from '@antv/g6'
const dialogVisible = ref(false)
const props = defineProps({
  watershedId: {
    type: Number,
    default: 1
  }
})
//验证
const rules = {
  rsysName: [{ required: true, message: '请输入河系名称', trigger: 'blur' }]
}
const riverFormRef = ref(null)
const multipleTableRef = ref(null)
let arr = {
  edges: [
    {
      source: '区域3',
      target: '区域1'
    },
    {
      source: '区域2',
      target: '区域1'
    },
    {
      source: '区域1',
      target: '区域1'
    }
  ],
  nodes: [
    {
      id: '区域1',
      label: '区域1'
    },
    {
      id: '区域2',
      label: '区域2'
    },
    {
      id: '区域3',
      label: '区域3'
    }
  ]
}
const state = reactive({
  childIdArr: [],
  flag: false,
  riverForm: {
    rsysName: '',
    rsysDesc: ''
  },
  title: '新建河系',
  graph: '',
  sec_topologData: {},
  checkedArr: [],
  tableData: [],
  selected: false,
  checkedObj: {
    edges: [],
    nodes: []
  }
})
function getAllArea() {
  getAreaList({ zoneId: props.watershedId }).then((res) => {
    if (res.code === 200) {
      state.tableData = res.data
    }
  })
}
function handleSelectable(row, index) {
  return !state.selected
}
function getParentId(id) {
  state.checkedObj.edges.forEach((edges) => {
    if (edges.target == id) {
      state.childIdArr.push(edges.source)
    }
  })
}
function handleSelectionChange(arr, e) {
  if (arr.filter((x) => e == x).length <= 0) {
    state.childIdArr = []
    getParentId(e.id)
    if (state.checkedObj.nodes.length) {
      state.checkedObj.nodes.splice(
        state.checkedObj.nodes.findIndex((child) => child.id == e.id),
        1
      )
      state.childIdArr.forEach((childId) => {
        state.checkedObj.nodes.splice(
          state.checkedObj.nodes.findIndex((child) => child.id == childId),
          1
        )
      })
    }
    state.checkedObj.edges.forEach((child, index) => {
      if (child.source == e.id || child.target == e.id) {
        delete state.checkedObj.edges[index]
      }
    })
    state.checkedObj.edges = state.checkedObj.edges.filter((d) => d)
    if (state.checkedObj.edges.length == 0) {
      state.checkedObj.nodes = []
    }
    multipleTableRef.value.clearSelection()
    state.tableData.forEach((item) => {
      state.checkedObj.nodes.forEach((e) => {
        if (item.id == e.id) {
          multipleTableRef.value.toggleRowSelection(item, true)
        }
      })
    })
    initG6(state.checkedObj)
    const clickNodes = state.graph.cfg.nodes
    clickNodes.forEach((item) => {
      if (item.getModel().id == state.checkedArr[0].id) {
        state.graph.setItemState(item, 'click', true)
      }
    })
    state.graph.refresh()
  } else {
    if (arr.length == 1) {
      arr.forEach((item, index) => {
        state.checkedObj.nodes.push({
          id: String(item.id),
          label: item.calczName
        })
        state.checkedObj.edges.push({
          source: String(item.id),
          target: String(item.id)
        })
      })
      initG6(state.checkedObj)
      state.graph.refresh()
    } else if (arr.length > 1) {
      //  state.checkedObj.edges =[]
      //   state.checkedObj.nodes = []
      arr.forEach((item, index) => {
        state.checkedObj.edges.push({
          source: String(item.id),
          target: state.checkedArr[0].id
        })
        state.checkedObj.nodes.push({
          id: String(item.id),
          label: item.calczName
        })
      })

      let map = new Map()
      state.checkedObj.edges = state.checkedObj.edges.filter(
        (v) => !map.has(v.source) && map.set(v.source, 1)
      )
      state.checkedObj.nodes = switchData(state.checkedObj.nodes)
      initG6(state.checkedObj)
      const clickNodes = state.graph.cfg.nodes
      clickNodes.forEach((item) => {
        if (item.getModel().id == state.checkedArr[0].id) {
          state.graph.setItemState(item, 'click', true)
        }
      })

      state.graph.refresh()
    }
  }
}
const emit = defineEmits(['closeRiver'])
const closeRiver = () => {
  emit('closeRiver', false)
}
function switchData(tempArr) {
  let result = []
  let obj = {}
  for (let i = 0; i < tempArr.length; i++) {
    if (!obj[tempArr[i].id]) {
      result.push(tempArr[i])
      obj[tempArr[i].id] = true
    }
  }
  return result
}
function handleOpenModal(value) {
  dialogVisible.value = true
  setTimeout(() => {
    initData()
    if (value) {
      setTimeout(() => {
        state.title = '修改河系'
        state.riverForm = { ...value }
      }, 100)
      getZoneList({ rsid: value.id }).then((res) => {
        if (res.code === 200) {
          res.data.forEach((item) => {
            state.checkedObj.edges.push({ source: String(item.zid), target: String(item.ozid) })
            state.checkedObj.nodes.push({ id: String(item.zid), label: item.zName })
          })
          initG6(state.checkedObj)
          state.tableData.forEach((item) => {
            state.checkedObj.nodes.forEach((e) => {
              if (item.id == e.id) {
                multipleTableRef.value.toggleRowSelection(item, true)
              }
            })
          })

          if (state.checkedObj.nodes.length) {
            state.selected = true
          }
        }
      })
    } else {
      state.title = '新建河系'
      //  state.riverForm ={}
    }
  }, 100)

  getAllArea()
  state.selected = false
}
function initData() {
  const container = document.getElementById('container')
  const width = container.clientWidth
  const height = container.clientHeight
  state.graph = new G6.Graph({
    container: container,
    width: width,
    height: height,
    plugins: [treeTooltip()],
    fitView: true,
    fitCenter: true,
    // "animate":true,
    fitViewPadding: [16, 16, 16, 16],
    modes: {
      default: ['zoom-canvas', 'drag-canvas', 'brush-select', 'node-select', 'click-select'],
      edit: ['click-select']
    },
    layout: {
      type: 'dagre',
      rankdir: 'TB',
      align: ''
    },
    defaultNode: {
      type: 'modelRect',
      style: {
        fill: '#ffffff',
        stroke: '#169bd5',
        cursor: 'pointer'
        // width: 120,
        // height: 60
      },
      preRect: {
        // 设置为false，则不显示
        show: false,
        fill: '#f759ab',
        width: 8
      },
      stateIcon: {
        show: false
      },
      labelCfg: {
        position: 'center',
        style: {
          textAlign: 'center',
          fontStyle: 'normal',
          color: '#169bd5'
          // whiteSpace:'nowrap',
          // overflow:'hidden',
          // textOverflow:'ellipsis'
        },

        offset: 80
      },
      anchorPoints: [
        [0.5, 0],
        [0.5, 1]
      ]
    },
    defaultEdge: {
      type: 'polyline',
      color: '#169bd5',
      style: {
        // "stroke": "rgb(79, 79, 79)",
        endArrow: {
          $arrowType: 'diy',
          $path: 'M 0,0 L 10,5 L 10,-5 Z',
          $compute: (e) => e,
          path: 'M 0,0 L 10,5 L 10,-5 Z',
          d: 5,
          fill: '#4a90e2',
          stroke: '#4a90e2'
        },
        cursor: 'default',
        //  "offset": 0  ,
        startArrow: {
          path: ''
        }
      }
    },
    nodeStateStyles: {
      // 鼠标 hover 上节点，即 hover 状态为 true 时的样式
      // hover: {
      //   fill: 'green'
      // },
      // 鼠标点击节点，即 click 状态为 true 时的样式
      click: {
        fill: '#409eff',
        color: '#fff'
      }
    },
    // 节点不同状态下的样式集合
    edgeStateStyles: {
      // 鼠标点击边，即 click 状态为 true 时的样式
      click: {
        // stroke: 'steelblue'
      }
    }
  })
}
// label 过长截断 显示...
const formatLabel = (node) => {
  const ellipsis = node.length > 10 ? '...' : ''
  return `${node.slice(0, 10)}${ellipsis}`
}
// label 显示... 时，显示提示 tip
const treeTooltip = () => {
  return new G6.Tooltip({
    offsetX: 10, // 鼠标偏移量
    offsetY: 20,
    shouldBegin(e) {
      return e.item?.get('model')?.label?.includes('...') // label中有...才显示，表示被截断
    },
    getContent(e) {
      let outDiv = document.createElement('div') // 设置tip容器和样式
      outDiv.innerHTML = `
      <p style="max-width:600px;word-wrap:break-word;border-radius:5px;font-size:15px;color:#fff;background:#333;padding:10px">
        ${e.item.getModel().name}
      </p>`
      return outDiv
    },
    itemTypes: ['node'] // 表示触发的元素类型
  })
}
function initG6(arr) {
  state.graph.node((node) => {
    return {
      label: formatLabel(node.label),
      id: node.id,
      name: node.name || node.label,
      type: 'modelRect',
      logoIcon: {
        // 是否显示icon，值为 false 则不渲染icon
        show: false,
        x: 0,
        y: 0,
        // icon的地址，字符串类型
        img: getMapAssetURL('sk.svg'),
        width: 16,
        height: 16,
        // 用于调整图标的左右位置
        offset: 0
      },
      style: {
        fill: '#96C94B'
      }
    }
  })
  //   const clickNodes = state.graph.findAllByState('node', 'click')
  //   if(clickNodes.length){
  // state.graph.setItemState(clickNodes[0], 'click', true)
  //   }

  // 读取数据
  state.graph.data(arr)
  // 渲染图
  state.graph.render()
  //点击节点
  state.graph.on('node:click', (e) => {
    // // 先将所有当前是 click 状态的节点置为非 click 状态
    //  state.graph.clearItemStates(clickNodes);
    const nodeItem = e.item // 获取被点击的节点元素对象
    state.graph.setItemState(nodeItem, 'click', state.flag == state.flag) // 设置当前节点的 click 状态为 true
    const clickNodes = state.graph.findAllByState('node', 'click')

    clickNodes.forEach((cn) => {
      if (cn._cfg.id != e.item._cfg.id) {
        state.graph.setItemState(cn, 'click', state.flag)
      }
    })
    state.checkedArr = clickNodes.map((item) => {
      return {
        id: item._cfg.model.id,
        label: item._cfg.model.label
      }
    })
    if (state.checkedArr.length) {
      state.selected = false
    } else {
      state.selected = true
    }
  })
}

defineExpose({ handleOpenModal })
//保存
function handleSave() {
  riverFormRef.value.validate(async (valid) => {
    if (valid) {
      let a = state.checkedObj.edges.map((item) => {
        return {
          zid: Number(item.source),
          ozid: Number(item.target)
        }
      })
      if (a.length <= 0) {
        ElMessage.warning('请选择输入区域')
        return false
      }
      if (state.riverForm.id) {
        state.riverForm = {
          rsysName: state.riverForm.rsysName,
          rsysDesc: state.riverForm.rsysDesc,
          zones: a,
          zoneId: props.watershedId,
          id: state.riverForm.id
        }
        ElMessageBox.confirm('河系修改，该河系下的区域方案将重置，是否修改?', '提示', {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning'
        })
          .then(() => {
            updateRiver(state.riverForm).then((res) => {
              if (res.code === 200) {
                ElMessage.success(res.msg)
                handleClose()
                closeRiver()
              }
            })
          })
          .catch(() => {})
      } else {
        state.riverForm = { ...state.riverForm, zones: a, zoneId: props.watershedId }
        addRiver(state.riverForm).then((res) => {
          if (res.code === 200) {
            ElMessage.success(res.msg)
            handleClose()
            closeRiver()
          }
        })
      }
    }
  })
}
function handleClose() {
  dialogVisible.value = false
  state.checkedObj.edges = []
  state.checkedObj.nodes = []
  riverFormRef.value.resetFields()
  state.graph.destroy()
}
onMounted(() => {})
</script>

<style lang="less" scoped>
.areaTable {
  height: 300px;
}
.river-modal {
  // width: 100%;
  // height: 100%;
  .my-header {
    height: 35px;
    border-bottom: 2px solid #eee;
  }
  .river-box {
    display: flex;
    width: 100%;
    height: 100%;
    :deep(.el-form) {
      width: 50%;
    }
    .box-right {
      width: 50%;
      margin: 30px 20px 20px 20px;
      background: #eee;
      #container {
        width: 100%;
        height: 100%;
        :deep(.g6-component-tooltip) {
          z-index: 2000;
          background: grey !important;
          div {
            background: grey !important;
            p {
              background: grey !important;
              color: #fff !important;
            }
          }
        }
      }
    }
  }
}
</style>
